
package com.lvmama.pangolin.busi.timer;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.lvmama.pangolin.common.ClassLoaderCache;
import com.lvmama.pangolin.common.StringTools;
import com.lvmama.pangolin.entity.Timer;
import com.lvmama.pangolin.service.TimerService;
import com.lvmama.pangolin.util.SpringContextUtil;

/**
 * @ClassName: TimerManager
 * @Description: TODO 定时任务管理类
 * @author yuanchi
 * @date 2017年1月17日 下午5:04:52
 */
public class TimerManager
{

	public static final String JOB_DATAKEY = "param";
	public static final String JOB_CODE = "JOB_CODE";
	public static final String TIMER_CODE = "TIMER_CODE";
	public static final String TASK_ID = "TASK_ID";
	public static final String TIMER_ID = "TIMER_ID";
	Logger logger = Logger.getLogger(TimerManager.class);
	private static TimerManager single;
	private Scheduler sched = null;
	private Map<String, CronTrigger> jobMap = null;
	private Map<String, Timer> timerMap = null;
	@Autowired
	private TimerService timerService;

	private TimerManager()
	{
		init();
	}

	/**
	 * 返回唯一实例
	 * 
	 * @return
	 */
	public static synchronized TimerManager getInstance()
	{
		if (single == null)
		{
			single = new TimerManager();
		}
		return single;
	}

	public void init()
	{
		try
		{
			logger.info("------- Initializing -------------------");
			SchedulerFactory sf = new StdSchedulerFactory();
			sched = sf.getScheduler();
			logger.info("------- Initialization Complete --------");
			ShutdownHook();
			logger.info("------- Scheduling Jobs ----------------");
			schedulerJob();
			logger.info("------- Starting Scheduler ----------------");
			sched.start();
			logger.info("------- Started Scheduler -----------------");
		}
		catch (Exception e)
		{
			logger.error("[TimerManager] 异常退出！", e);
			try
			{
				sched.shutdown(true);
			}
			catch (SchedulerException e1)
			{
				logger.error("[TimerManager] 关闭异常！", e1);
			}
		}
	}

	@SuppressWarnings("unchecked")
	public void schedulerJob() throws Exception
	{
		int timerCount = 0;
		Timer timerParam = new Timer();
		timerParam.setTimer_status("0");
		String syscode=System.getProperties().getProperty("SYSCODE");
		syscode = StringTools.isValid(syscode)?syscode:"PUBLIC";
		timerParam.setSyscode(syscode);
		timerParam.setTimer_valid(1);
		if (timerService == null)
		{
			timerService = (TimerService) SpringContextUtil.getBean(TimerService.class);
		}
		List<Timer> timerList = timerService.queryTimerList(timerParam);
		if (timerList != null && !timerList.isEmpty())
		{
			timerCount = timerList.size();
			if (jobMap == null)
				jobMap = new HashMap<String, CronTrigger>();
			if (timerMap == null)
			{
				timerMap = new HashMap<String, Timer>();
			}
			jobMap.clear();
			for (Timer timer : timerList)
			{
				String job_valid = String.valueOf(timer.getTimer_valid());
				if (!job_valid.equals("") && job_valid.trim().equalsIgnoreCase("1"))
				{
					try
					{
						String timerCode = timer.getTimer_code()+"_"+timer.getTask_id();
						String jobCode = timer.getJob_code();
						String className = timer.getTimer_classname();
						String classsParam = timer.getTimer_param();
						String timerCron = timer.getTimer_cron();
						Class jobClass = ClassLoaderCache.getClassByName(className);
						JobDetail job = JobBuilder.newJob(jobClass)
								.withIdentity("TIMER_" + timerCode)
								.usingJobData(TimerManager.TIMER_ID,timer.getTimer_id())
								.usingJobData(TimerManager.JOB_DATAKEY,classsParam)
								.usingJobData(TimerManager.JOB_CODE, jobCode)
								.usingJobData(TimerManager.TIMER_CODE, timerCode)
								.usingJobData(TimerManager.TASK_ID, timer.getTask_id())
								.build();
						CronTrigger trigger = (CronTrigger) TriggerBuilder
								.newTrigger()
								.withIdentity("TRG_" + timerCode)
								.withSchedule(CronScheduleBuilder.cronSchedule(timerCron))
								.build();
						sched.scheduleJob(job, trigger);
						jobMap.put(timerCode, trigger);
						timerMap.put(timerCode, timer);
					}
					catch (Exception e)
					{
						logger.error("启动定时任务：失败！", e);
					}
				}
			}
		}
		logger.info("启动定时任务:完成！数量：" + timerCount);
	}

	public Scheduler getScheduler()
	{
		return sched;
	}

	public void putScheduler(Scheduler scheduler)
	{
		sched = scheduler;
	}

	public Timer getTimer(String configName)
	{
		Timer timer = null;
		synchronized (timerMap)
		{
			timer = timerMap.get(configName);
		}
		return timer;
	}

	public void putTimer(String configName, Timer timer)
	{
		synchronized (timerMap)
		{
			timerMap.put(configName, timer);
		}
	}

	public void removeTimer(String configName)
	{
		synchronized (timerMap)
		{
			timerMap.remove(configName);
		}
	}

	public CronTrigger getCronTrigger(String configName)
	{
		CronTrigger trigger = null;
		synchronized (jobMap)
		{
			trigger = jobMap.get(configName);
		}
		return trigger;
	}

	public void putCronTrigger(String configName, CronTrigger crg)
	{
		synchronized (jobMap)
		{
			jobMap.put(configName, crg);
		}
	}

	public void removeTrigger(String configName)
	{
		synchronized (jobMap)
		{
			jobMap.remove(configName);
		}
	}

	public void ShutdownHook()
	{
		Runtime.getRuntime().addShutdownHook(new Thread()
		{

			@Override
			public void run()
			{
				logger.info("Shutting down...");
				try
				{
					sched.shutdown(true);
				}
				catch (SchedulerException e)
				{
					logger.error("[TimerManager] 关闭异常！", e);
				}
				logger.info("Stopped Timer.");
			}
		});
	}
}
